﻿using Microsoft.EntityFrameworkCore;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using XfTech.SmartTms.Entities;
using XfTech.SmartTms.Entities.BusinessAudit;
using XfTech.SmartTms.Entities.Issues;
using XfTech.SmartTms.Mappings;

namespace XfTech.SmartTms.EntityFrameworkCore
{
    [ReplaceDbContext(typeof(IIdentityDbContext))]
    [ReplaceDbContext(typeof(ITenantManagementDbContext))]
    [ConnectionStringName("Default")]
    public class SmartTmsDbContext :
        AbpDbContext<SmartTmsDbContext>,
        IIdentityDbContext,
        ITenantManagementDbContext
    {
        /* Add DbSet properties for your Aggregate Roots / Entities here. */

        #region Entities from the modules

        /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext
         * and replaced them for this DbContext. This allows you to perform JOIN
         * queries for the entities of these modules over the repositories easily. You
         * typically don't need that for other modules. But, if you need, you can
         * implement the DbContext interface of the needed module and use ReplaceDbContext
         * attribute just like IIdentityDbContext and ITenantManagementDbContext.
         *
         * More info: Replacing a DbContext of a module ensures that the related module
         * uses this DbContext on runtime. Otherwise, it will use its own DbContext class.
         */

        //Identity
        public DbSet<IdentityUser> Users { get; set; }
        public DbSet<IdentityRole> Roles { get; set; }
        public DbSet<IdentityClaimType> ClaimTypes { get; set; }
        public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
        public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
        public DbSet<IdentityLinkUser> LinkUsers { get; set; }

        // Tenant Management
        public DbSet<Tenant> Tenants { get; set; }
        public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }

        // 待办事项
        public DbSet<TodoItem> TodoItems { get; set; }
        public DbSet<Book> Books { get; set; }
        public DbSet<BookType> BookTypes { get; set; }

        //车辆
        public DbSet<Vehicle> Vehicles { get; set; }

        //审核信息
        public DbSet<Audit> AuditInfoes { get; set; }

        public DbSet<AuditLog> AuditLogs { get; set; }
        public DbSet<Issue> Issues { get; set; }
        public DbSet<Label> Labels { get; set; }
        public DbSet<IssueLabel> IssueLabels { get; set; }


        #endregion

        public SmartTmsDbContext(DbContextOptions<SmartTmsDbContext> options)
            : base(options)
        {

        }

        //这个重写的方法，OnModelCreating在数据模型被创建之前运行的。。
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            /* Include modules to your migration db context */

            builder.ConfigurePermissionManagement();
            builder.ConfigureSettingManagement();
            builder.ConfigureBackgroundJobs();
            builder.ConfigureAuditLogging();
            builder.ConfigureIdentity();
            builder.ConfigureIdentityServer();
            builder.ConfigureFeatureManagement();
            builder.ConfigureTenantManagement();

            /* Configure your own tables/entities inside here */

            //builder.Entity<YourEntity>(b =>
            //{
            //    b.ToTable(SmartTmsConsts.DbTablePrefix + "YourEntities", SmartTmsConsts.DbSchema);
            //    b.ConfigureByConvention(); //auto configure for the base class props
            //    //...
            //});

            //配置实体模型映射到数据模型的一些规则（百度：EfCore FluentAPI）
            builder.Entity<TodoItem>(b =>
            {
                b.ToTable("TodoItems");                      //表名
                b.Property("Text").HasMaxLength(200)         //长度
                                  .HasColumnName("ItemText") //数据库字段名称
                                  .HasColumnType("varchar")  //数据库字段类型
                                  .IsRequired();             //非空

            });

            //Book和BookType的映射配置（百度：EfCore FluentAPI）
            builder.Entity<Book>(b =>
            {
                b.ToTable("Books");
                b.Property("Name").HasMaxLength(50).IsRequired(); //Name varchar(50) not null
                b.Property("PublishDate").HasColumnType("date").IsRequired();
                b.Property("Price").HasPrecision(10, 2).IsRequired();

                //设置一对多关系
                b.HasOne<BookType>(t => t.Type).WithMany(b => b.Books).HasForeignKey(f => f.TId);
            });

            builder.Entity<BookType>(b =>
            {
                b.ToTable("BookTypes");
                b.Property("TName").HasMaxLength(40).IsRequired();
            });


            //应用VehicleMap映射配置类（此处演示将映射类写到一个单独的文件，方便维护）
            builder.ApplyConfiguration(new VehicleMap());

            //配置审核主表和日志表
            builder.Entity<Audit>(b =>
            {
                b.ToTable("BusinessAudits");
                b.ConfigureByConvention();
                b.Property("AuditPersonName").HasMaxLength(50);
                b.HasMany(a => a.AuditLogs).WithOne(l => l.AuditInfo).HasForeignKey(a => a.AuditId);
            });

            builder.Entity<AuditLog>(b =>
            {
                b.ToTable("BusinessAuditLogs");
                b.ConfigureByConvention();
                b.Property("ProcessPersonName").HasMaxLength(50).IsRequired();
                b.Property(p => p.Remark).HasMaxLength(300).IsRequired();
            });

            //配置 问题实体
            builder.Entity<Issue>(b =>
            {
                b.ToTable("Issues");
                b.ConfigureByConvention();
                b.Property(p => p.Title).HasMaxLength(50).IsRequired();
                b.Property(p => p.Text).HasMaxLength(200).IsRequired();

                //定义关系(一对多）
                b.HasMany(x => x.Labels)
                    .WithOne(x => x.Issue)
                    .HasForeignKey(x => x.IssueId)
                    .IsRequired();
            });

            //配置 标签实体
            builder.Entity<Label>(b =>
            {
                b.ToTable("Labels");
                b.Property(p => p.Name).HasMaxLength(20).IsRequired();
                b.Property(p => p.Color).HasMaxLength(10).IsRequired();

                //定义关系(一对多）
                b.HasMany(x => x.Issues)
                    .WithOne(x => x.Label)
                    .HasForeignKey(x => x.LabelId)
                    .IsRequired();

            });

                //配置 问题标签实体
            builder.Entity<IssueLabel>(b =>
            {
                b.ToTable("IssueLabels");
                b.ConfigureByConvention();
                
                b.HasKey(p => new { p.IssueId, p.LabelId }); //复合主键(两个字段做主键）
            });
        }
    }
}
